#include <iostream>
#include <memory>
#include <string>

// 抽象的水果类
class Fruit
{
public:
    Fruit()
    {
    }
    virtual void show() = 0;
};

// 水果类派生出的具体类
class Apple : public Fruit
{
public:
    Apple() {}
    void show() override
    {
        std::cout << "我是一个苹果!" << std::endl;
    }
};

class Banana : public Fruit
{
public:
    Banana() {}
    void show() override
    {
        std::cout << "我是一个香蕉!" << std::endl;
    }
};

//增加其他产品
class Animal
{
public:
    virtual void display() = 0;
};

class Dog : public Animal
{
public:
    void display() override
    {
        std::cout << "我是一只小狗!" << std::endl;
    }
};

class Goat : public Animal
{
public:
    void display() override 
    {
        std::cout << "我是一只山羊!" << std::endl;
    }
};

//抽象的工厂
class Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name) = 0;
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name) = 0;
};

class FruitFactory : public Factory
{
public:
    FruitFactory() {};
    std::shared_ptr<Fruit> getFruit(const std::string &name) override
    {
        if (name == "苹果")
        {
            return std::make_shared<Apple>();
        }
        else if (name == "香蕉")
        {
            return std::make_shared<Banana>();
        }

        return std::shared_ptr<Fruit>();
    }
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name)
    {
        return std::shared_ptr<Animal>();
    }
};

class AnimalFactory : public Factory
{
public:
    std::shared_ptr<Fruit> getFruit(const std::string& name) override
    {
        return std::shared_ptr<Fruit>();
    }
    std::shared_ptr<Animal> getAnimal(const std::string& name) override
    {
        if("小狗" == name)
        {
            return std::make_shared<Dog>();
        }
        else if("山羊" == name)
        {
            return std::make_shared<Goat>();
        }
        return std::shared_ptr<Animal>();
    }
};

int main()
{
    std::shared_ptr<Factory> factory = std::make_shared<FruitFactory>();
    std::shared_ptr<Fruit> fruit = factory->getFruit("苹果");
    fruit->show();
    fruit = factory->getFruit("香蕉");
    fruit->show();
    factory = std::make_shared<AnimalFactory>();
    std::shared_ptr<Animal> animal = factory->getAnimal("小狗");
    animal->display();
    animal = factory->getAnimal("山羊");
    animal->display();

    return 0;
}